package com.pengshun.modules.api.petrol.service.impl;

import com.pengshun.modules.aliyun.OosPush;
import com.pengshun.modules.api.coal.repository.UserRepository;
import com.pengshun.modules.api.coal.util.CommonUtil;
import com.pengshun.modules.api.coal.util.SystemPath;
import com.pengshun.modules.api.mapper.PetrolStationMapper;
import com.pengshun.modules.api.mapper.PsUserInComRecordMapper;
import com.pengshun.modules.api.mapper.PsUserInfoMapper;
import com.pengshun.modules.api.order.service.dto.IncomeRecordDto;
import com.pengshun.modules.api.order.service.mapstruct.IncomeRecordTodo;
import com.pengshun.modules.api.pay.service.DorderResult;
import com.pengshun.modules.api.pay.service.WechatPayService;
import com.pengshun.modules.api.petrol.service.JyPetrolStationOrderService;
import com.pengshun.modules.api.petrol.service.dto.JyPetrolStationEmployeeDto;
import com.pengshun.modules.api.petrol.service.dto.JyPetrolStationOrderDto;
import com.pengshun.modules.api.petrol.service.para.JyPetrolStationOrderPara;
import com.pengshun.modules.api.petrol.service.repository.JyPetrolStationOrderRepository;
import com.pengshun.modules.api.petrol.service.repository.JyPetrolStationProductRepository;
import com.pengshun.modules.api.petrol.service.repository.JyPetrolStationRealRepository;
import com.pengshun.modules.api.petrol.service.repository.JyPetrolStationRepository;
import com.pengshun.modules.api.user.repository.IncomeRecordRepository;
import com.pengshun.modules.api.user.repository.IncomeRepository;
import com.pengshun.modules.api.user.service.dto.QrcodeDto;
import com.pengshun.modules.common.BaseResult;
import com.pengshun.modules.common.BillType;
import com.pengshun.modules.common.OrderCommon;
import com.pengshun.modules.common.PagePara;
import com.pengshun.modules.domain.*;
import lombok.AllArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.image.BufferedImage;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import static com.pengshun.modules.api.util.QRCodeUtils.createImage;
import static com.pengshun.modules.api.util.QRCodeUtils.upoos;

/**
 * @author luoligang
 * @create 2021/6/30
 */
@Service
@AllArgsConstructor
public class JyPetrolStationOrderServiceImpl implements JyPetrolStationOrderService {

    private final JyPetrolStationProductRepository productRepository;
    private final JyPetrolStationRepository stationRepository;
    private final JyPetrolStationOrderRepository orderRepository;
    private final PetrolStationMapper petrolStationMapper;
    private final IncomeRepository incomeRepository;
    private final WechatPayService wechatPayService;
    private final MessageSource messageSource;
    private final UserRepository userRepository;
    private final PsUserInfoMapper userInfoMapper;
    private final PsUserInComRecordMapper uirm;
    private final IncomeRecordRepository incomeRecordRepository;
    private final IncomeRecordTodo incomeRecordTodo;
    private final JyPetrolStationRealRepository realRepository;
    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult add(JyPetrolStationOrderPara para) throws Exception {
        Income income = incomeRepository.findByUserId(para.getBuyUserId());
        User users = userRepository.findById(para.getBuyUserId()).orElseGet(User::new);
        //支付方式(1油气卡支付2余额支付3微信支付4支付支付)
        if (para.getPayWay() == 1 && income.getOilCardBlanace().compareTo(para.getRealAmount()) <0) {
            return new BaseResult(messageSource.getMessage("JyPetrolStationOrderServiceImpl.add.getOilCardBlanace.err", null, Locale.CHINA));
        }
        if (para.getPayWay() == 2 && income.getUsableBlanace().compareTo(para.getRealAmount()) <0) {
            return new BaseResult(messageSource.getMessage("JyPetrolStationOrderServiceImpl.add.getUsableBlanace.err", null, Locale.CHINA));
        }
        if (para.getPayWay() < 3) {
            if (para.getPayPass() == null) {
                return new BaseResult(1, messageSource.getMessage("FreightSettlementServiceImpl.pay.payPss.null", null, Locale.CHINA));
            }
            //验证支付密码是否正确
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            if (!bCryptPasswordEncoder.matches(para.getPayPass(), users.getPayPass())) {
                return new BaseResult(5, messageSource.getMessage("FreightSettlementServiceImpl.pay.payPss.error", null, Locale.CHINA));
            }
            if (!users.getEnabled()) {
                //说明用户被禁用
                return new BaseResult( messageSource.getMessage("FreightSettlementServiceImpl.pay.user.getEnabled", null, Locale.CHINA));
            }
        }
        //验证金额计算是否正确
        //查询商品当前活动
        List<JyPetrolStationActivity> aclist=petrolStationMapper.activityList(para.getPetrolStationProductId());
        //优惠金额
        BigDecimal activityAmount=new BigDecimal(0);
        for (JyPetrolStationActivity activity : aclist) {
            //最终优惠
            BigDecimal lastAmount=new BigDecimal(0);
            for (JyPetrolStationActivityDetil detil : activity.getDetils()) {
                if(para.getStationAmount().compareTo(detil.getFullReductionAmount())>=0){
                    lastAmount=detil.getMitigateAmount();
                }
            }
            activityAmount=activityAmount.add(lastAmount);
        }

        String settNo = "PTY" + CommonUtil.getFourRandom();
        JyPetrolStationProduct product = productRepository.findById(para.getPetrolStationProductId()).orElseGet(JyPetrolStationProduct::new);
        JyPetrolStation station = stationRepository.findById(product.getPetrolStationId()).orElseGet(JyPetrolStation::new);
        activityAmount=activityAmount.add((product.getStationPrice().subtract(product.getNowPrice())).multiply(para.getStationNum()));
        if(activityAmount.compareTo(para.getDiscountsAmount())!=0){
            //优惠金额计算有误
            return new BaseResult( messageSource.getMessage("JyPetrolStationOrderServiceImpl.pay.discountsAmount.error", null, Locale.CHINA));
        }
        //保存订单
        JyPetrolStationOrder order = new JyPetrolStationOrder();
        order.setPetrolStationGunId(para.getPetrolStationGunId());
        order.setGunName(para.getGunName());
        order.setPetrolStationProductId(para.getPetrolStationProductId());
        order.setStationName(product.getStationName());
        order.setSettNo(settNo);
        order.setCarOwnerId(para.getCarOwnerId());
        order.setCarOwnerNum(para.getCarOwnerNum());
        order.setName(station.getName());
        order.setDetailAddress(station.getDetailAddress());
        order.setPetrolStationId(station.getPetrolStationId());
        order.setBuyUserId(para.getBuyUserId());
        order.setStationPrice(product.getStationPrice());
        order.setUserRebates(product.getUserRebates());
        order.setNowPrice(product.getNowPrice());
        order.setStationNum(para.getStationNum());
        order.setStationAmount(para.getStationAmount());
        order.setDiscountsAmount(para.getDiscountsAmount());
        order.setRealAmount(para.getRealAmount());
        order.setSettTime(new Date());
        order.setPayWay(para.getPayWay());
        order.setPayStatus(2);
        orderRepository.save(order);
        if (para.getPayWay() == 3) {
            order.setPayStatus(1);
            //微信支付
            String attach = para.getBuyUserId() + "-" + BillType.BILL_TYPE_NINE + "-" + order.getPetrolStationOrderId();
            Integer waitPayMoney = para.getRealAmount().multiply(new BigDecimal(100)).intValue();
            DorderResult resuls= wechatPayService.unifiedorder("加油费用支付", waitPayMoney, attach, "APP", "");
            resuls.setId(order.getPetrolStationOrderId());
            return new BaseResult(0,resuls);
        } else {
            List<JyPetrolStationEmployeeDto> list = userInfoMapper.findByPetrolStationId(station.getPetrolStationId());
            JyPetrolStationEmployeeDto admin = new JyPetrolStationEmployeeDto();
            for (JyPetrolStationEmployeeDto user : list) {
                if ("管理员".equals(user.getRole())) {
                    admin = user;
                }
            }
            Income merchantUser = incomeRepository.findByUserId(admin.getUserId());
            if(merchantUser==null){
                throw new Exception("加油站暂无员工");
            }
            BigDecimal needPayMoney = para.getRealAmount();
            //用户通知
            OosPush.push("付款通知", "您的账户支出油款" + needPayMoney + "元", "ALIAS", users.getAlias());
            for (JyPetrolStationEmployeeDto user : list) {
                //商户通知
                OosPush.push("到账通知", "您的账户收入油款" + needPayMoney + "元", "ALIAS", user.getAlias());
            }

            Long merUserId = merchantUser.getUserId();

            //更新商户账户余额
            BigDecimal nowBlanace = merchantUser.getUsableBlanace().add(needPayMoney);
            BigDecimal userNowAccountBlanace = merchantUser.getAccountBlanace().add(needPayMoney);
            uirm.updateBlanace(merchantUser.getUsableBlanace(), nowBlanace, merUserId, merchantUser.getAccountBlanace(), userNowAccountBlanace);
            //商户账单表添加数据
            IncomeRecordDto incomeRecord = new IncomeRecordDto(merUserId, settNo, needPayMoney, OrderCommon.BPAYMENT_TYPE_ONE, BillType.BILL_TYPE_TEN, order.getPetrolStationOrderId(),
                    OrderCommon.PAY_WAY_ONE, "加油收入", 1, new Date(), 1, users.getName(), users.getAvatarName(), null);
            incomeRecordRepository.save(incomeRecordTodo.toEntity(incomeRecord));
            if (para.getPayWay() == 1) {
                //更新用户油气卡余额
                BigDecimal oldblanace = income.getOilCardBlanace();
                BigDecimal newBlanace = income.getOilCardBlanace().subtract(needPayMoney);
                uirm.updateOilBlanace( oldblanace,newBlanace,income.getUserId());
                //待结算用户账单表添加数据
                IncomeRecordDto userIncomeRecord = new IncomeRecordDto(income.getUserId(), settNo, needPayMoney, OrderCommon.PAYMENT_TYPE_TWO, BillType.BILL_TYPE_NINE, order.getPetrolStationOrderId(),
                        OrderCommon.PAY_WAY_ONE, "加油支付", 1, new Date(), 1, admin.getName(), admin.getLogo(), null);
                incomeRecordRepository.save(incomeRecordTodo.toEntity(userIncomeRecord));
            }
            if (para.getPayWay() == 2) {
                //更新用户余额
                BigDecimal userNowBlanace = income.getUsableBlanace().subtract(needPayMoney);
                BigDecimal userNowAccountBlanaces = income.getAccountBlanace().subtract(needPayMoney);
                uirm.updateBlanace(income.getUsableBlanace(), userNowBlanace, income.getUserId(), income.getAccountBlanace(), userNowAccountBlanaces);
                //待结算用户账单表添加数据
                IncomeRecordDto userIncomeRecord = new IncomeRecordDto(income.getUserId(), settNo, needPayMoney, OrderCommon.PAYMENT_TYPE_TWO, BillType.BILL_TYPE_NINE, order.getPetrolStationOrderId(),
                        OrderCommon.PAY_WAY_TWO, "加油支付", 1, new Date(), 1, admin.getName(), admin.getLogo(), null);
                incomeRecordRepository.save(incomeRecordTodo.toEntity(userIncomeRecord));
            }
        }
        return new BaseResult(0,order);
    }

    @Override
    public BaseResult orderList(PagePara para) {
        List<JyPetrolStationOrderDto> orderDtoList = petrolStationMapper.selectOrderList(para.getPage(), para.getSize(), para.getUserId());
        return new BaseResult(0, orderDtoList);
    }

    @Override
    public BaseResult detil(Long petrolStationOrderId) {
        JyPetrolStationOrder order=orderRepository.findById(petrolStationOrderId).orElseGet(JyPetrolStationOrder::new);
        return new BaseResult(0,order);
    }

    @Override
    public BaseResult merchantOrderList(PagePara page, JyPetrolStationOrderDto para,Long userId) {
        //查询加油站id
        Long petrolStationId=petrolStationMapper.selectPetrolStationId(userId);
        List<JyPetrolStationOrderDto> orderDtoList = petrolStationMapper.merchantOrderList(page.getPage(), page.getSize(),petrolStationId,
                para.getUpdateBy(),para.getCarOwnerNum(),para.getStartDate(),para.getEndDate());
        return new BaseResult(0, orderDtoList);
    }

    @Override
    public BaseResult qrcode(Long userId, JyPetrolStationOrderDto para) throws Exception {
        String name =petrolStationMapper.selectPetrolStationEmpName(userId);
        para.setUpdateBy(name);
        BufferedImage image=createImage("4,"+para.getPetrolStationGunId());
        String url=upoos(image);
        //删除key
        redisTemplate.delete(SystemPath.APP_ORDER_PAY_QRCODE_PATH +para.getPetrolStationGunId());
        //订单信息存入redis 过期时间设置暂定为5分钟  过期将不可用   设置有效期5分钟
        redisTemplate.boundValueOps(SystemPath.APP_ORDER_PAY_QRCODE_PATH + para.getPetrolStationGunId()).set(para, 5, TimeUnit.MINUTES);
        return new BaseResult(0,new QrcodeDto(url));
    }

    @Override
    public BaseResult orderUpdate(Long userId, Long petrolStationOrderId) {
        String name =petrolStationMapper.selectPetrolStationEmpName(userId);
        JyPetrolStationOrder order=orderRepository.findById(petrolStationOrderId).orElseGet(JyPetrolStationOrder::new);
        order.setUpdateBy(name);
        order.setSureStatus(2);
        orderRepository.save(order);
        return new BaseResult(0);
    }

    @Override
    public BaseResult stationDetil(Long id) {
        Long petrolStationId=petrolStationMapper.selectPetrolStationId(id);
        JyPetrolStation station=stationRepository.findById(petrolStationId).orElseGet(JyPetrolStation::new);
        return new BaseResult(0,station);
    }

    @Override
    public BaseResult stationUpdate(Long id, Integer cooperateState) {
        Long petrolStationId=petrolStationMapper.selectPetrolStationId(id);
        JyPetrolStation station=stationRepository.findById(petrolStationId).orElseGet(JyPetrolStation::new);
        station.setCooperateState(cooperateState);
        return new BaseResult(0);
    }

    @Override
    public BaseResult productList(Long id) {
        Long petrolStationId=petrolStationMapper.selectPetrolStationId(id);
        List<JyPetrolStationProduct> list=productRepository.findByPetrolStationIdOrderByPetrolStationProductId(petrolStationId);
        return new BaseResult(0,list);
    }

    @Override
    public BaseResult productUddate(Long id, JyPetrolStationProduct para) {
        JyPetrolStationProduct product=productRepository.findById(para.getPetrolStationProductId()).orElseGet(JyPetrolStationProduct::new);
        if (product.getUserRebates() != null) {
            BigDecimal nowPrice = (new BigDecimal(100).subtract(product.getUserRebates())).divide(new BigDecimal(100)).multiply(product.getStationPrice());
            product.setStationPrice(para.getStationPrice());
            product.setNowPrice(nowPrice);
        }else{
            product.setStationPrice(para.getStationPrice());
            product.setNowPrice(para.getStationPrice());
        }
        return new BaseResult(0);
    }

    @Override
    public BaseResult stationReal(Long id, JyPetrolStationReal para) {
        realRepository.save(para);
        return new BaseResult(0);
    }
}
